package main

import (
	"crypto/sha256"
	"fmt"
	"math/big"
)

type ProofOfWork struct {
	block  *Block
	target *big.Int
}

func NewProofOfWork(block *Block) *ProofOfWork {
	pow := ProofOfWork{
		block: block,
	}
	targetStr := "0001000000000000000000000000000000000000000000000000000000000000"
	tmpInt := big.Int{}
	tmpInt.SetString(targetStr, 16)
	pow.target = &tmpInt
	return &pow
}

func (pow *ProofOfWork) Run() ([]byte, uint64) {
	var nonce uint64
	var hash [32]byte
	block := pow.block
	for {
		var blockInfo []byte
		blockInfo = append(blockInfo, block.PrevHash...)
		blockInfo = append(blockInfo, Uint64ToByte(block.Version)...)
		blockInfo = append(blockInfo, Uint64ToByte(block.TimeStamp)...)
		blockInfo = append(blockInfo, Uint64ToByte(block.Difficulty)...)
		blockInfo = append(blockInfo, Uint64ToByte(nonce)...)
		blockInfo = append(blockInfo, block.MerkelRoot...)
		//blockInfo = append(blockInfo, block.Data...)
		hash = sha256.Sum256(blockInfo)
		tmpInt := big.Int{}
		tmpInt.SetBytes(hash[:])
		if tmpInt.Cmp(pow.target) == -1 {
			fmt.Printf("挖矿成功！hash:%x,nonce:%d\n", hash, nonce)
			break
		} else {
			//fmt.Printf("挖矿失败! nonce:%d\n", nonce)
			nonce++
		}
	}
	return hash[:], nonce
}
